﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Routing;
using System.Web.Mvc;
using MvcEngine.Mvc.Routing;
using MvcEngine.Core.HttpHandlers;

namespace MvcEngine.Mvc.Extensions
{
    public static class AreaRegistrationContextExtensions
    {
        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url)
        {
            return context.MapMvcEngineRoute(name, url, (object)null, null, null);
        }

        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url, object defaults)
        {
            return context.MapMvcEngineRoute(name, url, defaults, null, null);
        }

        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url, string[] namespaces)
        {
            return context.MapMvcEngineRoute(name, url, null, null, namespaces, null);
        }

        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url, string[] namespaces, IRouteHandler handler)
        {
            return context.MapMvcEngineRoute(name, url, null, null, namespaces, handler);
        }

        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url, object defaults, object constraints)
        {
            return context.MapMvcEngineRoute(name, url, defaults, constraints, null, null);
        }

        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url, object defaults, IRouteHandler handler)
        {
            return context.MapMvcEngineRoute(name, url, defaults, null, null, handler);
        }


        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url, object defaults, string[] namespaces)
        {
            return context.MapMvcEngineRoute(name, url, defaults, null, namespaces, null);
        }

        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url, object defaults, string[] namespaces, IRouteHandler handler)
        {
            return context.MapMvcEngineRoute(name, url, defaults, null, namespaces, handler);
        }

        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url, object defaults, object constraints, string[] namespaces)
        {
            return context.MapMvcEngineRoute(name, url, new RouteValueDictionary(defaults), constraints, namespaces, null);
        }

        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url, RouteValueDictionary defaults, object constraints, string[] namespaces)
        {
            return context.MapMvcEngineRoute(name, url, defaults, constraints, namespaces, null);
        }


        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url, object defaults, object constraints, string[] namespaces, IRouteHandler handler)
        {
            return context.MapMvcEngineRoute(name, url, new RouteValueDictionary(defaults), constraints, namespaces, handler);
        }

        public static Route MapMvcEngineRoute(this AreaRegistrationContext context, string name, string url, RouteValueDictionary defaults, object constraints, string[] namespaces, IRouteHandler handler)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (url == null)
            {
                throw new ArgumentNullException("url");
            }

            if(handler == null)
                handler = new MvcEngineRouteHandler();

            MvcEngineRoute item = new MvcEngineRoute(url, handler);
            item.Defaults = defaults;
            item.Constraints = new RouteValueDictionary(constraints);
            item.DataTokens = new RouteValueDictionary();
            if ((namespaces != null) && (namespaces.Length > 0))
            {
                if (!namespaces.Any(n => n == "MvcEngine.Mvc.BackOffice.Controllers") && !namespaces.Any(n => n == "MvcEngine.Mvc.StarterSite.Controllers"))
                {
                    List<string> newNamespaces = new List<string>((IEnumerable<string>)namespaces);
                    newNamespaces.Add("MvcEngine.Mvc.BackOffice.Controllers");
                    namespaces = newNamespaces.ToArray();
                }
                item.DataTokens["Namespaces"] = namespaces;
            }
            item.DataTokens["area"] = context.AreaName;
            bool useNamespaceFallback = (namespaces == null || namespaces.Length == 0);
            item.DataTokens["UseNamespaceFallback"] = useNamespaceFallback;
            item.DataTokens["RouteName"] = name;

            context.Routes.Add(name, item);

            return item;
        }






        #region Module routes

        public static Route MapModuleRoute(this AreaRegistrationContext context, string name, string url, object defaults)
        {
            return context.MapModuleRoute(name, url, defaults, null, null);
        }

        public static Route MapModuleRoute(this AreaRegistrationContext context, string name, string url, object defaults, string[] namespaces)
        {
            return context.MapModuleRoute(name, url, defaults, null, namespaces);
        }

        public static Route MapModuleRoute(this AreaRegistrationContext context, string name, string url, object defaults, object constraints, string[] namespaces)
        {
            var dictionary = BuildDefaults(defaults);
            dictionary["action"] = "Index";

            if (namespaces.Any(n => n != "MvcEngine.Mvc.StarterSite.Controllers"))
            {
                List<string> newNamespaces = new List<string>((IEnumerable<string>)namespaces);
                newNamespaces.Add("MvcEngine.Mvc.StarterSite.Controllers");
                namespaces = newNamespaces.ToArray();
            }

            return context.MapMvcEngineRoute(name, url, dictionary, constraints, namespaces);
        }

        private static RouteValueDictionary BuildDefaults(object defaults)
        {
            var dictionary = new RouteValueDictionary(defaults);
            dictionary["controller"] = "Home";
            return dictionary;
        }

        #endregion

        #region Image routes

        public static void MapImageRoute(this AreaRegistrationContext context, String name, String url, object defaults, IFileResolver fileResolver)
        {
            context.MapImageRoute(name, url, defaults, null, fileResolver, null);
        }

        public static void MapImageRoute(this AreaRegistrationContext context, String name, String url, IFileResolver fileResolver, string[] namespaces)
        {
            context.MapImageRoute(name, url, new RouteValueDictionary(), null, fileResolver, namespaces);
        }

        public static void MapImageRoute(this AreaRegistrationContext context, String name, String url, object defaults, IFileResolver fileResolver, string[] namespaces)
        {
            context.MapImageRoute(name, url, defaults, null, fileResolver, namespaces);
        }

        public static void MapImageRoute(this AreaRegistrationContext context, String name, String url, object defaults, object constraints, IFileResolver fileResolver, string[] namespaces)
        {
            MvcEngineRoute item = new MvcEngineRoute(url, new FileRouteHandler(fileResolver));
            item.Defaults = new RouteValueDictionary(defaults);
            item.Constraints = new RouteValueDictionary(constraints);

            if ((namespaces != null) && (namespaces.Length > 0))
            {
                item.DataTokens = new RouteValueDictionary();
                item.DataTokens["Namespaces"] = namespaces;
            }
            item.DataTokens["RouteName"] = name;
            //bool useNamespaceFallback = (namespaces == null || namespaces.Length == 0);
            //item.DataTokens["UseNamespaceFallback"] = useNamespaceFallback;

            //item.DataTokens["area"] = context.AreaName;

            context.Routes.Add(name, item);
        }

        #endregion

    }
}


